package com.clear.club.circle.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.clear.club.circle.api.enums.IsDeletedFlagEnum;
import com.clear.club.circle.api.req.GetShareCommentReplyReq;
import com.clear.club.circle.api.req.RemoveShareCommentReplyReq;
import com.clear.club.circle.api.req.SaveShareCommentReplyReq;
import com.clear.club.circle.api.vo.ShareCommentReplyVO;
import com.clear.club.circle.server.dao.ShareMomentMapper;
import com.clear.club.circle.server.entity.po.ShareCommentReply;
import com.clear.club.circle.server.dao.ShareCommentReplyMapper;
import com.clear.club.circle.server.entity.po.ShareMoment;
import com.clear.club.circle.server.service.ShareCommentReplyService;
import com.clear.club.circle.server.util.TreeUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 评论及回复信息(ShareCommentReply)表服务实现类
 *
 * @author makejava
 * @since 2024-07-03 18:05:54
 */
@Service("shareCommentReplyService")
public class ShareCommentReplyServiceImpl extends ServiceImpl<ShareCommentReplyMapper, ShareCommentReply> implements ShareCommentReplyService {

    @Resource
    private ShareMomentMapper shareMomentMapper;

    /**
     * 发布内容   评论或回复
     *
     * @param req
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public Boolean saveComment(SaveShareCommentReplyReq req) {
        // 1.查询原始动态内容：这一步可得到原始动态作者信息，用于后续判断是否是作者
        ShareMoment shareMoment = shareMomentMapper.selectById(req.getMomentId());
        // 2.数据copy req ==> shareCommentReply
        ShareCommentReply shareCommentReply = new ShareCommentReply();
        // 原始动态id
        shareCommentReply.setMomentId(req.getMomentId());
        // 回复类型
        shareCommentReply.setReplyType(req.getReplyType());
        // 内容
        shareCommentReply.setContent(req.getContent());
        if (!CollectionUtils.isEmpty(req.getPicUrlList())) {
            //  图片内容
            shareCommentReply.setPicUrls(JSON.toJSONString(req.getPicUrlList()));
        }
        // 3.获取当前用户
        // todo 暂时写死
        String loginId = "小黑子卤出鸡脚";
        // 4.根据回复类型进行数据组装   1评论 2回复
        if (req.getReplyType() == 1) {
            // 评论父id为-1
            shareCommentReply.setParentId(-1L);
            // 评论目标id：即当前评论评论的动态内容id
            shareCommentReply.setToId(req.getTargetId());
            // 评论人
            shareCommentReply.setToUser(loginId);
            // 判断评论人是否是作者
            if (Objects.nonNull(shareMoment.getCreatedBy())) {
                shareCommentReply.setToUserAuthor(loginId.equals(shareMoment.getCreatedBy()) ? 1 : 0);
            }
        } else if (req.getReplyType() == 2) {
            // 回复父id为目标id
            shareCommentReply.setParentId(req.getTargetId());
            // 回复目标id：即当前回复回复的评论id
            shareCommentReply.setReplyId(req.getTargetId());
            // 回复人
            shareCommentReply.setReplyUser(loginId);
            // 判断回复人是否是作者
            if (Objects.nonNull(shareMoment.getCreatedBy())) {
                shareCommentReply.setReplayAuthor(loginId.equals(shareMoment.getCreatedBy()) ? 1 : 0);
            }
        }
        shareCommentReply.setCreatedBy(loginId);
        shareCommentReply.setCreatedTime(new Date());
        shareCommentReply.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());

        // 动态增加回复数
        shareMomentMapper.incrReplyCount(shareMoment.getId(), 1);

        return this.save(shareCommentReply);
    }

    /**
     * 删除评论或回复
     *
     * @param req
     */
    @Override
    public Boolean removeComment(RemoveShareCommentReplyReq req) {
        // 1.先根据id（评论id或回复id）查询po
        ShareCommentReply comment = this.getById(req.getId());
        // 2.查询出该动态内容下所有的评论及回复
        LambdaQueryWrapper<ShareCommentReply> queryWrapper = Wrappers.<ShareCommentReply>lambdaQuery()
                .eq(ShareCommentReply::getMomentId, comment.getMomentId())
                .eq(ShareCommentReply::getIsDeleted, IsDeletedFlagEnum.UN_DELETED.getCode())
                // 评论（或回复）id
                .select(ShareCommentReply::getId,
                        // 动态id
                        ShareCommentReply::getMomentId,
                        // 回复类型
                        ShareCommentReply::getReplyType,
                        // 内容
                        ShareCommentReply::getContent,
                        // 图片
                        ShareCommentReply::getPicUrls,
                        // 创建人
                        ShareCommentReply::getCreatedBy,
                        // 评论人   // todo 查询出的这个字段是否多余？
                        ShareCommentReply::getToUser,
                        // 父id
                        ShareCommentReply::getParentId
                );
        List<ShareCommentReply> list = this.list(queryWrapper);

        // 3.将所有的评论及回复组装成树结构
        List<ShareCommentReply> tree = TreeUtils.buildTree(list);
        // 4.我猜 是 根据id（评论id或回复id）取查找级联子对象
        // 比如说如果当前是 评论，则查找评论及其回复 回复的回复
        //      如果说是 回复，则查找当前回复及其回复的回复
        ArrayList<ShareCommentReply> replyList = new ArrayList<>();
        for (ShareCommentReply reply : tree) {
            TreeUtils.findAll(replyList, reply, req.getId());
        }
        // 关联子级对象及 moment 的回复数量
        // 例如：update share_comment_reply set is_deleted=1 where id in (1,2,3) and moment_id = 5;
        Set<Long> replyIds = replyList.stream().map(ShareCommentReply::getId).collect(Collectors.toSet());
        LambdaUpdateWrapper<ShareCommentReply> updateWrapper = Wrappers.<ShareCommentReply>lambdaUpdate()
                .eq(ShareCommentReply::getMomentId, comment.getMomentId())
                .in(ShareCommentReply::getId, replyIds)
                .set(ShareCommentReply::getIsDeleted, IsDeletedFlagEnum.DELETED.getCode());
        boolean result = this.update(updateWrapper);

        // 动态减少回复数
        shareMomentMapper.incrReplyCount(comment.getMomentId(), -replyIds.size());
        return result;
    }

    /**
     * 查询动态下的评论
     */
    @Override
    public List<ShareCommentReplyVO> listComment(GetShareCommentReplyReq req) {
        // 1.查询出该动态内容下所有的评论及回复
        // 例如：select id,moment_id,reply_type,content,pic_urls,created_by,to_user,pic_urls from share_comment_reply where moment_id=5 and is_deleted=0;
        LambdaQueryWrapper<ShareCommentReply> queryWrapper = Wrappers.<ShareCommentReply>lambdaQuery()
                // 动态内容id
                .eq(ShareCommentReply::getMomentId, req.getId())
                .eq(ShareCommentReply::getIsDeleted, IsDeletedFlagEnum.UN_DELETED.getCode())
                // 评论id 或 回复id
                .select(ShareCommentReply::getId,
                        ShareCommentReply::getMomentId,
                        ShareCommentReply::getReplyType,
                        ShareCommentReply::getContent,
                        ShareCommentReply::getPicUrls,
                        ShareCommentReply::getCreatedBy,
                        // todo 查询出的这个字段是否多余？
                        ShareCommentReply::getToUser,
                        ShareCommentReply::getParentId
                );
        List<ShareCommentReply> list = this.list(queryWrapper);
        // 2.将查询结果进行z转换 po ==> vo
        List<ShareCommentReplyVO> voList = list.stream().map(item -> {
            ShareCommentReplyVO vo = new ShareCommentReplyVO();
            vo.setId(item.getId());
            vo.setMomentId(item.getMomentId());
            vo.setReplyType(item.getReplyType());
            vo.setContent(item.getContent());
            if (Objects.nonNull(item.getPicUrls())) {
                vo.setPicUrlList(JSONArray.parseArray(item.getPicUrls(), String.class));
            }
            // 回复
            if (item.getReplyType() == 2) {
                vo.setFromId(item.getCreatedBy());
                vo.setToId(item.getToUser());
            }
            vo.setParentId(item.getParentId());
            return vo;
        }).collect(Collectors.toList());
        // 3.利用工具类将评论及回复组织成 树结构 并返回
        return TreeUtils.buildTree(voList);
    }
}
